﻿Imports System
Imports System.CodeDom
Imports System.Collections
Imports System.Collections.Generic
Imports System.Reflection

Namespace System.Workflow.ComponentModel.Compiler
    Friend Class Helper
        ' Methods
        Friend Shared Function ConvertToFieldAttributes(ByVal memberAttributes As MemberAttributes) As FieldAttributes
            Dim privateScope As FieldAttributes = FieldAttributes.PrivateScope
            If ((memberAttributes And MemberAttributes.AccessMask) = MemberAttributes.Assembly) Then
                privateScope = (privateScope Or FieldAttributes.Assembly)
            ElseIf ((memberAttributes And MemberAttributes.AccessMask) = MemberAttributes.Family) Then
                privateScope = (privateScope Or FieldAttributes.Family)
            ElseIf ((memberAttributes And MemberAttributes.AccessMask) = MemberAttributes.FamilyAndAssembly) Then
                privateScope = (privateScope Or FieldAttributes.FamANDAssem)
            ElseIf ((memberAttributes And MemberAttributes.AccessMask) = MemberAttributes.FamilyOrAssembly) Then
                privateScope = (privateScope Or FieldAttributes.FamORAssem)
            ElseIf ((memberAttributes And MemberAttributes.AccessMask) = MemberAttributes.Private) Then
                privateScope = (privateScope Or FieldAttributes.Private)
            ElseIf ((memberAttributes And MemberAttributes.AccessMask) = MemberAttributes.Public) Then
                privateScope = (privateScope Or FieldAttributes.Public)
            End If
            If ((memberAttributes And MemberAttributes.ScopeMask) = MemberAttributes.Const) Then
                Return (privateScope Or (FieldAttributes.Literal Or FieldAttributes.Static))
            End If
            If ((memberAttributes And MemberAttributes.ScopeMask) = MemberAttributes.Static) Then
                privateScope = (privateScope Or FieldAttributes.Static)
            End If
            Return privateScope
        End Function

        Friend Shared Function ConvertToMethodAttributes(ByVal memberAttributes As MemberAttributes) As MethodAttributes
            Dim reuseSlot As MethodAttributes = MethodAttributes.ReuseSlot
            If ((memberAttributes And MemberAttributes.AccessMask) = MemberAttributes.Assembly) Then
                reuseSlot = (reuseSlot Or MethodAttributes.Assembly)
            ElseIf ((memberAttributes And MemberAttributes.AccessMask) = MemberAttributes.Family) Then
                reuseSlot = (reuseSlot Or MethodAttributes.Family)
            ElseIf ((memberAttributes And MemberAttributes.AccessMask) = MemberAttributes.FamilyAndAssembly) Then
                reuseSlot = (reuseSlot Or MethodAttributes.FamANDAssem)
            ElseIf ((memberAttributes And MemberAttributes.AccessMask) = MemberAttributes.FamilyOrAssembly) Then
                reuseSlot = (reuseSlot Or MethodAttributes.FamORAssem)
            ElseIf ((memberAttributes And MemberAttributes.AccessMask) = MemberAttributes.Private) Then
                reuseSlot = (reuseSlot Or MethodAttributes.Private)
            ElseIf ((memberAttributes And MemberAttributes.AccessMask) = MemberAttributes.Public) Then
                reuseSlot = (reuseSlot Or MethodAttributes.Public)
            End If
            If ((memberAttributes And MemberAttributes.ScopeMask) = MemberAttributes.Abstract) Then
                reuseSlot = (reuseSlot Or MethodAttributes.Abstract)
            ElseIf ((memberAttributes And MemberAttributes.ScopeMask) = MemberAttributes.Final) Then
                reuseSlot = (reuseSlot Or MethodAttributes.Final)
            ElseIf ((memberAttributes And MemberAttributes.ScopeMask) = MemberAttributes.Static) Then
                reuseSlot = (reuseSlot Or MethodAttributes.Static)
            End If
            If ((memberAttributes And MemberAttributes.VTableMask) = MemberAttributes.New) Then
                reuseSlot = (reuseSlot Or MethodAttributes.VtableLayoutMask)
            End If
            Return reuseSlot
        End Function

        Friend Shared Function ConvertToParameterAttributes(ByVal direction As FieldDirection) As ParameterAttributes
            Select Case direction
                Case FieldDirection.In
                    Return ParameterAttributes.In
                Case FieldDirection.Out
                    Return ParameterAttributes.Out
            End Select
            Return ParameterAttributes.None
        End Function

        Friend Shared Function ConvertToTypeAttributes(ByVal memberAttributes As MemberAttributes, ByVal declaringType As Type) As TypeAttributes
            Dim autoLayout As TypeAttributes = TypeAttributes.AutoLayout
            If ((memberAttributes And MemberAttributes.AccessMask) = MemberAttributes.Assembly) Then
                autoLayout = (autoLayout Or If((Not declaringType Is Nothing), 5, 0))
            ElseIf ((memberAttributes And MemberAttributes.AccessMask) = MemberAttributes.Family) Then
                autoLayout = (autoLayout Or If((Not declaringType Is Nothing), 4, 0))
            ElseIf ((memberAttributes And MemberAttributes.AccessMask) = MemberAttributes.FamilyAndAssembly) Then
                autoLayout = (autoLayout Or If((Not declaringType Is Nothing), 6, 0))
            ElseIf ((memberAttributes And MemberAttributes.AccessMask) = MemberAttributes.FamilyOrAssembly) Then
                autoLayout = (autoLayout Or If((Not declaringType Is Nothing), 7, 0))
            ElseIf ((memberAttributes And MemberAttributes.AccessMask) = MemberAttributes.Private) Then
                autoLayout = (autoLayout Or If((Not declaringType Is Nothing), 3, 0))
            ElseIf ((memberAttributes And MemberAttributes.AccessMask) = MemberAttributes.Public) Then
                autoLayout = (autoLayout Or If((Not declaringType Is Nothing), 2, 1))
            End If
            If ((memberAttributes And MemberAttributes.ScopeMask) = MemberAttributes.Abstract) Then
                Return (autoLayout Or TypeAttributes.Abstract)
            End If
            If ((memberAttributes And MemberAttributes.ScopeMask) = MemberAttributes.Final) Then
                Return (autoLayout Or TypeAttributes.Sealed)
            End If
            If ((memberAttributes And MemberAttributes.Static) = MemberAttributes.Static) Then
                autoLayout = (autoLayout Or (TypeAttributes.Sealed Or TypeAttributes.Abstract))
            End If
            Return autoLayout
        End Function

        Friend Shared Function EnsureTypeName(ByVal typeName As String) As String
            If ((Not typeName Is Nothing) AndAlso (typeName.Length <> 0)) Then
                If (typeName.IndexOf("."c) = -1) Then
                    If typeName.StartsWith("@", StringComparison.Ordinal) Then
                        typeName = typeName.Substring(1)
                        Return typeName
                    End If
                    If (typeName.StartsWith("[", StringComparison.Ordinal) AndAlso typeName.EndsWith("]", StringComparison.Ordinal)) Then
                        typeName = typeName.Substring(1, (typeName.Length - 1))
                    End If
                    Return typeName
                End If
                Dim strArray As String() = typeName.Split(New Char() { "."c })
                typeName = String.Empty
                Dim index As Integer = 0
                Do While (index < (strArray.Length - 1))
                    typeName = (typeName & Helper.EnsureTypeName(strArray(index)))
                    typeName = (typeName & ".")
                    index += 1
                Loop
                typeName = (typeName & Helper.EnsureTypeName(strArray(index)))
            End If
            Return typeName
        End Function

        Friend Shared Function GetCustomAttributes(ByVal attributeType As Type, ByVal inherit As Boolean, ByVal attributes As Attribute(), ByVal memberInfo As MemberInfo) As Object()
            If (attributeType Is Nothing) Then
                Throw New ArgumentNullException("attributeType")
            End If
            Dim list As New ArrayList
            Dim list2 As New ArrayList
            If (attributeType Is GetType(Object)) Then
                list.AddRange(attributes)
            Else
                Dim attribute As AttributeInfoAttribute
                For Each attribute In attributes
                    If (attribute.AttributeInfo.AttributeType Is attributeType) Then
                        list.Add(attribute)
                        list2.Add(attributeType)
                    End If
                Next
            End If
            If inherit Then
                Dim baseType As MemberInfo = Nothing
                If TypeOf memberInfo Is Type Then
                    baseType = DirectCast(memberInfo, Type).BaseType
                Else
                    baseType = DirectCast(memberInfo.DeclaringType, DesignTimeType).GetBaseMember(memberInfo.GetType, memberInfo.DeclaringType.BaseType, (BindingFlags.NonPublic Or (BindingFlags.Public Or (BindingFlags.Static Or BindingFlags.Instance))), New MemberSignature(memberInfo))
                End If
                If (Not baseType Is Nothing) Then
                    Dim attribute2 As Attribute
                    For Each attribute2 In baseType.GetCustomAttributes(attributeType, inherit)
                        If (Not TypeOf attribute2 Is AttributeInfoAttribute OrElse Not list2.Contains(DirectCast(attribute2, AttributeInfoAttribute).AttributeInfo.AttributeType)) Then
                            list.Add(attribute2)
                        End If
                    Next
                End If
            End If
            Return list.ToArray
        End Function

        Friend Shared Function IncludeAccessor(ByVal accessor As MethodInfo, ByVal nonPublic As Boolean) As Boolean
            If (accessor Is Nothing) Then
                Return False
            End If
            Return (nonPublic OrElse accessor.IsPublic)
        End Function

        Friend Shared Function IsDefined(ByVal attributeType As Type, ByVal inherit As Boolean, ByVal attributes As Attribute(), ByVal memberInfo As MemberInfo) As Boolean
            If (attributeType Is Nothing) Then
                Throw New ArgumentNullException("attributeType")
            End If
            Dim attribute As Attribute
            For Each attribute In attributes
                If (TypeOf attribute Is AttributeInfoAttribute AndAlso ([TryCast](attribute,AttributeInfoAttribute).AttributeInfo.AttributeType Is attributeType)) Then
                    Return True
                End If
            Next
            Dim baseType As MemberInfo = Nothing
            If TypeOf memberInfo Is Type Then
                baseType = DirectCast(memberInfo, Type).BaseType
            Else
                baseType = DirectCast(memberInfo.DeclaringType, DesignTimeType).GetBaseMember(memberInfo.GetType, memberInfo.DeclaringType.BaseType, (BindingFlags.NonPublic Or (BindingFlags.Public Or (BindingFlags.Static Or BindingFlags.Instance))), New MemberSignature(memberInfo))
            End If
            Return ((Not baseType Is Nothing) AndAlso baseType.IsDefined(attributeType, inherit))
        End Function

        Friend Shared Function LoadCustomAttributes(ByVal codeAttributeCollection As CodeAttributeDeclarationCollection, ByVal declaringType As DesignTimeType) As Attribute()
            If (declaringType Is Nothing) Then
                Throw New ArgumentNullException("declaringType")
            End If
            If (codeAttributeCollection Is Nothing) Then
                Return New Attribute(0  - 1) {}
            End If
            Dim list As New List([Of] Attribute)
            Dim declaration As CodeAttributeDeclaration
            For Each declaration In codeAttributeCollection
                Dim argumentNames As String() = New String(declaration.Arguments.Count  - 1) {}
                Dim argumentValues As Object() = New Object(declaration.Arguments.Count  - 1) {}
                Dim attributeType As Type = declaringType.ResolveType(declaration.Name)
                If (Not attributeType Is Nothing) Then
                    Dim index As Integer = 0
                    Dim argument As CodeAttributeArgument
                    For Each argument In declaration.Arguments
                        argumentNames(index) = argument.Name
                        If TypeOf argument.Value Is CodePrimitiveExpression Then
                            argumentValues(index) = [TryCast](argument.Value,CodePrimitiveExpression).Value
                        ElseIf TypeOf argument.Value Is CodeTypeOfExpression Then
                            argumentValues(index) = argument.Value
                        ElseIf TypeOf argument.Value Is CodeSnippetExpression Then
                            argumentValues(index) = [TryCast](argument.Value,CodeSnippetExpression).Value
                        Else
                            argumentValues(index) = New ArgumentException(SR.GetString("Error_TypeSystemAttributeArgument"))
                        End If
                        index += 1
                    Next
                    Dim flag As Boolean = False
                    Dim attribute As AttributeInfoAttribute
                    For Each attribute In list
                        If attribute.AttributeInfo.AttributeType.FullName.Equals(attributeType.FullName) Then
                            flag = True
                            Exit For
                        End If
                    Next
                    Dim allowMultiple As Boolean = False
                    If (flag AndAlso (Not attributeType.Assembly Is Nothing)) Then
                        Dim customAttributes As Object() = attributeType.GetCustomAttributes(GetType(AttributeUsageAttribute), True)
                        If ((Not customAttributes Is Nothing) AndAlso (customAttributes.Length > 0)) Then
                            Dim attribute2 As AttributeUsageAttribute = [TryCast](customAttributes(0),AttributeUsageAttribute)
                            allowMultiple = attribute2.AllowMultiple
                        End If
                    End If
                    If (Not flag OrElse allowMultiple) Then
                        list.Add(AttributeInfoAttribute.CreateAttributeInfoAttribute(attributeType, argumentNames, argumentValues))
                    End If
                End If
            Next
            Return list.ToArray
        End Function

    End Class
End Namespace

